#version 430 core

layout (binding = 2) uniform sampler2D U_MainTexture;
layout (binding = 1) uniform sampler2D x_Texture;
uniform samplerCube skybox;
in vec3 gs_normal;
in vec4 gs_worldPos;
in vec2 gs_texcoord;
uniform vec3 lightPos;
uniform vec3 viewPos;


/* S型函数, log形式 */
void log_sigmoid(out float result, in float x, in float dx, in float coefficient)
{
    result = 1.0f/(1.0f+exp((x - dx) * coefficient));
}

// 绕轴旋转
void rotation(out mat3 r, in vec3 k, in float theta)
{
    float C = 1-cos(theta);
   	r = mat3( 
       cos(theta)+k.x*k.x*C, -sin(theta)*k.z+k.x*k.y*C, sin(theta)*k.y+k.x*k.z*C,
       sin(theta)*k.z+k.x*k.y*C, cos(theta)+k.y*k.y*C, -sin(theta)*k.x+k.y*k.z*C,
       -sin(theta)*k.y+k.x*k.z*C, sin(theta)*k.x+k.y*k.z*C, cos(theta)+k.z*k.z*C);
	// 列主序，需要转置
	r = transpose(r);
}

void main()
{
	/* 光源参数 */ 
	float edgeSoftness = 20.0f;				// 参数边缘柔和度 越大越锐利	
	float lightDiameter = 0.1f;				// 光源的直径
	vec3 lightColor = vec3(1.0f,1.0f,1.0f); // 光线颜色
	float lightIntensity = 600.0f;			// 光照强度
	float ambientIntensity = 0.4f;			// 环境光强度

	/* 材料参数 */ 
	vec3 n2 = vec3(1.58f, 1.62f, 1.64f);    	// 材料表面涂层折射率
	float materialAbsorptivity = 0.1;		// 材料表面涂层的吸收率
	//vec4 objectColor = texture2D(U_MainTexture, gs_texcoord); 			// 材料纹理
	//vec4 objectColor = vec4(50.0f/256.0f,130.0f/256.0f,220.0f/256.0f,1.0f);	// 材料颜色
	//vec4 objectColor = vec4(235.0f/256.0f,70.0f/256.0f,90.0f/256.0f,1.0f);	// 材料颜色
	vec4 objectColor = vec4(23.0f/256.0f,25.0f/256.0f,40.0f/256.0f,1.0f);	// 材料颜色
	float environment = 0.2f;				// 环境反射系数
	float diffuseIntensity = 0.03f;			// 漫反射强度
	float sparkling = 0.80f; 				// 亮晶晶亮度反射系数
	float glittering = 0.55f;				// 调节亮晶晶的重要系数
	//float glittering = 0.28f;				// 调节亮晶晶的重要系数
	//float glittering = 0.5f;				// 调节亮晶晶的重要系数

	/* 预计算一些量 */
	// 光线矢量
	vec3 lightDirection = normalize(lightPos - gs_worldPos.xyz); 
	// 光线距离
	float lightDistance = distance(lightPos, gs_worldPos.xyz);
	// 视线矢量	
	vec3 viewDirection = normalize(viewPos - gs_worldPos.xyz);  	
	// 相机距离
	float viewDistance = distance(viewPos, gs_worldPos.xyz);  	
	// 法线
 	vec3 normal = normalize(gs_normal);//*vec3(-1,1,-1); 		

	// -50为经验值，反映了衍射边界的过度性质的强度衰减
	float coefficientDiffraction;
	log_sigmoid(coefficientDiffraction, dot(normal, lightDirection), 0.0f, -20.0f);
	// S型函数后期衰减过慢，截断以避免bug
	if(coefficientDiffraction<0.1) 
		coefficientDiffraction = 0.0f;
	// 面元接收到的发光强度(虽然强度与距离的平方成反比，但是考虑人对光线的动态调节，只做线性处理)
	// float coefficientlightIntensity = lightIntensity / (lightDistance*lightDistance);
	float coefficientlightIntensity = lightIntensity / lightDistance;
	// 入射光强S偏振强度
	vec3 lightIntensity_S = lightColor * coefficientlightIntensity * 0.5f;
	// 入射光强P偏振强度
	vec3 lightIntensity_P = lightColor * coefficientlightIntensity * 0.5f;
	// n1/n2折射系数，1.0f为空气折射率 
	vec3 eta = vec3(1.0f)/n2;  		
	// 模型直接反射光矢量
	vec3 lightDirectionReflect = reflect(-lightDirection, normal); 	
	// 模型直接反射视线矢量
	vec3 viewDirectionReflect = reflect(-viewDirection, normal); 			 
	// 模型折射光矢量
	vec3 refractDir_r = refract(lightDirection, -normal, eta.x);               
	vec3 refractDir_g = refract(lightDirection, -normal, eta.y);         
	vec3 refractDir_b = refract(lightDirection, -normal, eta.z);    
	// 视线折射矢量
	vec3 viewRefractDir_r = refract(viewDirection, -normal, eta.x);               
	vec3 viewRefractDir_g = refract(viewDirection, -normal, eta.y);         
	vec3 viewRefractDir_b = refract(viewDirection, -normal, eta.z);  
	//gl_FragColor = vec4(viewRefractDir_r, 1.0f);

	// 入射角
	float theta1 = acos(dot(normal, lightDirection)); 	
	// 折射角
	float theta2_r = asin(sin(theta1)*eta.x); 
	float theta2_g = asin(sin(theta1)*eta.y); 
	float theta2_b = asin(sin(theta1)*eta.z); 
	// 表面反射振幅比 P偏振
	float rp_r = tan(theta1-theta2_r)/tan(theta1+theta2_r);
	float rp_g = tan(theta1-theta2_g)/tan(theta1+theta2_g);
	float rp_b = tan(theta1-theta2_b)/tan(theta1+theta2_b);
	// 表面透射振幅比 P偏振
	float tp_r = 2.0f*sin(theta2_r)*cos(theta1)/(sin(theta1+theta2_r)*cos(theta1-theta2_r));
	float tp_g = 2.0f*sin(theta2_g)*cos(theta1)/(sin(theta1+theta2_g)*cos(theta1-theta2_g));
	float tp_b = 2.0f*sin(theta2_b)*cos(theta1)/(sin(theta1+theta2_b)*cos(theta1-theta2_b));
	// 反射能流密度比 P偏振
	float rwp_r = rp_r * rp_r;
	float rwp_g = rp_g * rp_g;
	float rwp_b = rp_b * rp_b;
	// 透射能流密度比 P偏振
	float twp_r = tp_r * tp_r;
	float twp_g = tp_g * tp_g;
	float twp_b = tp_b * tp_b;
	// 表面反射振幅比 S偏振
	float rs_r = -sin(theta1-theta2_r)/sin(theta1+theta2_r);
	float rs_g = -sin(theta1-theta2_g)/sin(theta1+theta2_g);
	float rs_b = -sin(theta1-theta2_b)/sin(theta1+theta2_b);
	// 表面透射振幅比 S偏振
	float ts_r= 2.0f*sin(theta2_r)*cos(theta1)/sin(theta1+theta2_r);
	float ts_g= 2.0f*sin(theta2_g)*cos(theta1)/sin(theta1+theta2_g);
	float ts_b= 2.0f*sin(theta2_b)*cos(theta1)/sin(theta1+theta2_b);
	// 反射能流密度比 S偏振
	float rws_r = rs_r * rs_r;
	float rws_g = rs_g * rs_g;
	float rws_b = rs_b * rs_b;
	// 透射能流密度比 S偏振
	float tws_r = ts_r * ts_r;
	float tws_g = ts_g * ts_g;
	float tws_b = ts_b * ts_b;

	// 反射光强
	vec3 lightIntensityReflect = lightIntensity_S * vec3(rws_r, rws_g, rws_b) + 
		lightIntensity_P * vec3(rwp_r, rwp_g, rwp_b);

	// 透射光强
	vec3 lightIntensityRefract = lightIntensity_S * vec3(tws_r, tws_g, tws_b) + 
		lightIntensity_P * vec3(twp_r, twp_g, twp_b);

	// 应用吸收率
	lightIntensityRefract = lightIntensityRefract * (1-materialAbsorptivity);

	// 检查菲涅尔公式
	// gl_FragColor = vec4(lightIntensityReflect+lightIntensityRefract, 1.0f);

	// 光源所占视角(之前重复考虑了视线距离带来的影响那部分已经被视角矩阵考虑过了)
	float lightPerspective = lightDiameter/lightDistance; 
	
	// 计算视角带来的权重 	
	float weightVsualAngle;
	log_sigmoid(weightVsualAngle, acos(dot(lightDirection, 
		viewDirectionReflect)), lightPerspective, edgeSoftness);
	
/* 全面镜面反射 */
	vec3 CompleteSpecularReflection = coefficientDiffraction * 
		lightIntensityReflect * weightVsualAngle;
	//gl_FragColor = vec4(CompleteSpecularReflection, 1.0f);

	// 法线纹理
	vec4 textureNormal = texture2D(x_Texture, gs_texcoord*10000);    // 越大纹理越细
	//gl_FragColor = vec4(textureNormal.xyz, 1.0f);
	// 纹理法线，法线空间
	vec3 normalTextureTexture = normalize(textureNormal.xyz*2.0-1.0);
	
	// 纹理法线
	vec3 normalTexture = normal;
	// 偏转角度亮晶晶法线角度
	float theta = acos(dot(vec3(0.0f,0.0f,1.0f), normalTextureTexture));
	if (theta > 0.000001f)
	{
		mat3 R;
		rotation(R, cross(vec3(0.0f,0.0f,1.0f), normalTextureTexture), theta);
		normalTexture = R*normal;
	}

	// 折射反射视线矢量(纹理法线)
	vec3 viewDirectionReflectTexture_r = reflect(-viewRefractDir_r, normalTexture); 		
	vec3 viewDirectionReflectTexture_g = reflect(-viewRefractDir_g, normalTexture); 	
	vec3 viewDirectionReflectTexture_b = reflect(-viewRefractDir_b, normalTexture); 	
	//gl_FragColor = vec4(textureNormal.xyz, 1.0f);

	// 漫反射的边缘要柔和很多
	float edgeSoftnessDiffuse = edgeSoftness * glittering;
	// 计算视角带来的权重(纹理法线)
	float weightVsualAngle_r;
	log_sigmoid(weightVsualAngle_r, acos(dot(refractDir_r, 
		viewDirectionReflectTexture_r)), lightPerspective, edgeSoftnessDiffuse);
	float weightVsualAngle_g;
	log_sigmoid(weightVsualAngle_g, acos(dot(refractDir_g, 
		viewDirectionReflectTexture_g)), lightPerspective, edgeSoftnessDiffuse);
	float weightVsualAngle_b;
	log_sigmoid(weightVsualAngle_b, acos(dot(refractDir_b, 
		viewDirectionReflectTexture_b)), lightPerspective, edgeSoftnessDiffuse);

/* 纹理法线的镜面反射 */
	vec3 CompleteSpecularReflectionTexture = coefficientDiffraction \
		* lightIntensityRefract * vec3(weightVsualAngle_r, weightVsualAngle_g, weightVsualAngle_b) \
		* objectColor.xyz * sparkling * sqrt(1/viewDistance);
	//gl_FragColor = vec4(CompleteSpecularReflectionTexture , 1.0f);


	// 漫反射强度
	float diffuse_r = dot(normal, refractDir_r);
	float diffuse_g = dot(normal, refractDir_g);
	float diffuse_b = dot(normal, refractDir_b);

/* 漫反射强度 */
	vec3 diffuseTexture = coefficientDiffraction * lightIntensityRefract * 
		vec3(diffuse_r, diffuse_g, diffuse_b) * objectColor.xyz * diffuseIntensity ;	
	// gl_FragColor = vec4(diffuseTexture, 1.0f);

/* 环境光 */
    vec3 ambient = ambientIntensity * lightColor * objectColor.xyz;
	//gl_FragColor = vec4(ambient, 1.0f);

/* 环境映射 */
    vec3 EnvironmentMapping = texture(skybox, viewDirectionReflect).xyz;
	//gl_FragColor = textureNormal;//vec4(normalTexture, 1.0f);
	//gl_FragColor = vec4(CompleteSpecularReflectionTexture, 1.0f);
	//gl_FragColor = vec4(diffuseTexture, 1.0f);
	gl_FragColor = vec4(EnvironmentMapping*environment + ambient + CompleteSpecularReflectionTexture + diffuseTexture + CompleteSpecularReflection, 0.0f);
}

